/*—————————————————————————————————————————————————————————— menu导航栏组件 ——————————————————————————————————————————————————————————*/
import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react'
// 公共配置数据
import config from '@/common/config/config'

// 公共方法引入
// --------------------------------------------------------------------------------------------------------
import { combinationItems } from './tool' // 导航栏组合成员函数
import { useNavigate, useLocation } from 'react-router-dom'

// 用户信息内存操作函数集
import {
  getUserSelectMenu, // 获取用户选中的菜单
  setUserSelectMenu, // 设置用户选中的菜单
  getUserOpenMenu, // 获取用户展开的菜单
  setUserOpenMenu, // 设置用户展开的菜单
} from '@/utils/userMessage'

// redux全类型hooks引入
// --------------------------------------------------------------------------------------------------------
import { useAppSelector } from '@/utils/hooks'

// 组件引入
// --------------------------------------------------------------------------------------------------------
import { Menu, MenuProps } from 'antd'

// 组件书写区
// ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
const MenuBox: React.FC = () => {
  const [items, setItems] = useState([]) // 导航栏成员
  const [open, setOpen] = useState<Array<string>>([]) // 默认展开成员数据
  const [select, setSelect] = useState<Array<string>>([]) // 默认选中成员数据
  const navigate = useNavigate() // 路由操作方法
  const location = useLocation()
  const { userMenu } = useAppSelector((state) => state.publicStore) // 获取本页面的index模块数据,并结构出用户菜单

  // 计算当前跳转菜单查询选择内容
  // --------------------------------------------------------------------------------------------------------
  const selectOpenMap = useMemo(() => {
    // 判断当前redux中的用户菜单数组是否存在且有值，若没有则进行赋予兜底数据
    const menus = userMenu && userMenu.length ? userMenu : config.standbyMenu

    // 声明返回选中的中间值
    const selects = {}

    // 声明选中菜单的中间值
    const opens = {}

    // 循环当前的菜单数据
    // =========================================================================================
    menus.forEach((value) => {
      // 如果存在子集表单则进行对子集成员遍历，并添加到选中中间值中
      if (value.children?.length) {
        value.children.forEach((val) => {
          selects[val.key] = [value.key, val.key]
          opens[val.key] = [value.key]
        })
      } else {
        // 没有则将此成员本身添加进
        selects[value.key] = [value.key]
        opens[value.key] = [value.key]
      }
    })

    return { selects, opens }
  }, [userMenu])

  // 在组件挂载前进行判断
  // --------------------------------------------------------------------------------------------------------
  useLayoutEffect(() => {
    // 判断当前redux中的用户菜单数组是否存在且有值，若没有则进行赋予兜底数据
    const menus = userMenu && userMenu.length ? userMenu : config.standbyMenu

    // 获取到当前内存中的用户选中菜单信息
    // =========================================================================================
    let selectMenu = getUserSelectMenu()
    let openMenu = getUserOpenMenu()

    // 如果都没有，则进行赋予兜底数据
    // =========================================================================================
    !selectMenu && (selectMenu = config.standbySelectMenu)
    !openMenu && (openMenu = config.standbyOpenMenu)

    // 设置并同步当前的数据，且按照组件需要内容进行赋值
    // =========================================================================================
    setItems(combinationItems(menus))
    setSelect(selectMenu)
    setOpen(openMenu)
  }, [userMenu])

  // 路由发生改变时
  // --------------------------------------------------------------------------------------------------------
  useEffect(() => {
    // 获取当前选中与展开的对应参数
    const selectList = selectOpenMap.selects[location.pathname]
    const openList = selectOpenMap.opens[location.pathname]

    // 获取当前内存中的打开菜单
    const oldOpenList = getUserOpenMenu() || []

    // 当选中成员存在时，才能进行改变当前的选中成员和内存中的值
    // =========================================================================================
    selectList &&
      setSelect(() => {
        setUserSelectMenu(selectList)
        return selectList
      })

    // 当展开成员列表存在 并且 此时内存的存储成员中没有此时的展开成员
    // =========================================================================================
    openList?.length &&
      !oldOpenList?.includes(openList[0]) &&
      setOpen(() => {
        // 则将当前页面的成员信息放入内存数据中进行更新同步
        const newOpenList = oldOpenList.concat(openList)
        setUserOpenMenu(newOpenList)
        return newOpenList
      })
  }, [location.pathname])

  // 被选中时调用
  // --------------------------------------------------------------------------------------------------------
  const itemSelect: MenuProps['onSelect'] = (itemMsg) => {
    // 跳转至对应页面
    navigate(itemMsg.key)
    setUserSelectMenu(itemMsg.keyPath)
  }

  // 菜单展开状态改变时调用
  // --------------------------------------------------------------------------------------------------------
  const itemOpen: MenuProps['onOpenChange'] = (openKeys) => {
    // 同步此时的展开成员与内存中的成员值
    setOpen(openKeys)
    setUserOpenMenu(openKeys)
  }

  return (
    <Menu
      style={{
        borderInlineEnd: 'none',
        overflow: 'auto',
        height: '80vh',
      }}
      mode="inline"
      inlineIndent={16}
      items={items}
      // 展开和选中的数据
      openKeys={open}
      selectedKeys={select}
      // 成员被选中时触发
      onSelect={itemSelect}
      // 展开时点击函数
      onOpenChange={itemOpen}
    />
  )
}

export default MenuBox
